/**
 * 绘制十字路口的Canvas对象
 * @author niuroumian
 * @time 2017/10/27 
 */

(function(global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.CanvasCross = factory());
}(this, function() {
    "use strict";

    function CanvasCross(selector, options) {
        this.selector = selector;
        this.options = options;
        this.init();
    }
    //获取元素
    CanvasCross.prototype.getDom = function(element) {
        return document.querySelector(element);
    };
    //获取元素的宽
    CanvasCross.prototype.getWidth = function(Dom) {
        return Dom.offsetWidth;
    };
    //获取元素的宽
    CanvasCross.prototype.getHeight = function(Dom) {
        return Dom.offsetHeight;
    };
    //初始化canvas
    CanvasCross.prototype.init = function() {
        this.addCanvas();
        this.draw();
    };
    //设置大小
    CanvasCross.prototype.addCanvas = function() {
        var canvas = this.canvas = document.createElement('canvas');
        var ctx = this.ctx = canvas.getContext('2d');
        this.dom = this.getDom(this.selector);
        this.width = this.getWidth(this.dom);
        this.height = this.getHeight(this.dom);
        canvas.width = this.width;
        canvas.height = this.height;
        canvas.style.width = canvas.width + "px";
        canvas.style.height = canvas.height + "px";
        this.dom.appendChild(canvas);
    };
    CanvasCross.prototype.draw = function() {
        var ctx = this.ctx;
        //顶点
        var x1 = this.x1 = 0,
            x2 = this.x2 = this.width / 2 - this.options.vertical.width / 2,
            x3 = this.x3 = this.width / 2 + this.options.vertical.width / 2,
            x4 = this.x4 = this.width,
            y1 = this.y1 = 0,
            y2 = this.y2 = this.height / 2 - this.options.horizontal.width / 2,
            y3 = this.y3 = this.height / 2 + this.options.horizontal.width / 2,
            y4 = this.y4 = this.height;
        var points = {
            leftTop: [
                [x1, y2],
                [x2, y2],
                [x2, y1]
            ],
            rightTop: [
                [x4, y2],
                [x3, y2],
                [x3, y1]
            ],
            leftBottom: [
                [x1, y3],
                [x2, y3],
                [x2, y4]
            ],
            rightBottom: [
                [x4, y3],
                [x3, y3],
                [x3, y4]
            ]
        };
        for (var c in points) {
            this.curve(ctx, points[c]);
        }
        this.road(ctx);
        this.crosswalk(ctx);
        this.drive(ctx);
        this.text(ctx);
        this.compass(ctx);
    };
    //绘制指南针
    CanvasCross.prototype.compass = function(ctx){
        ctx.save();
        ctx.font = parseInt(this.options.compass.size)+"px"+ " Arial";
        //ctx.fontSize = this.options.compass.size + "px";
        ctx.fillStyle = "#fff";
        ctx.beginPath();
        ctx.fillText(this.options.compass.name, this.x4 - parseInt(this.options.compass.right), parseInt(this.options.compass.top));
        ctx.restore();

        ctx.save();
        ctx.fillStyle = "#636363";
        ctx.beginPath();
        ctx.translate(this.x4 - parseInt(this.options.compass.right)+ parseInt(this.options.compass.size) /2, parseInt(this.options.compass.top)+10);
        ctx.moveTo(0, 0);
        ctx.lineTo(0, 20);
        ctx.lineTo(10, 30);
        ctx.closePath();
        ctx.fill();
        ctx.restore();
        ctx.save();
        ctx.fillStyle = "#fff";
        ctx.beginPath();
        ctx.translate(this.x4 - parseInt(this.options.compass.right) + parseInt(this.options.compass.size)/2, parseInt(this.options.compass.top)+10);
        ctx.moveTo(0, 0);
        ctx.lineTo(0, 20);
        ctx.lineTo(-10, 30);
        ctx.closePath();
        ctx.fill();
        ctx.restore();
    }
    //四个拐角线段
    CanvasCross.prototype.curve = function(ctx, points) {
        ctx.save();
        ctx.strokeStyle = '#7C7C7C';
        ctx.lineWidth = 5;
        ctx.beginPath();
        ctx.moveTo(points[0][0], points[0][1]);
        ctx.arcTo(points[1][0], points[1][1], points[2][0], points[2][1], this.options.radius);
        ctx.lineTo(points[2][0], points[2][1]);
        ctx.stroke();
        ctx.restore();
    };
    // draw road
    CanvasCross.prototype.road = function(ctx) {
        ctx.save();
        ctx.fillStyle = "#092f49";
        ctx.beginPath();
        ctx.moveTo(this.x1, this.y2);
        ctx.arcTo(this.x2, this.y2, this.x2, this.y1, this.options.radius);
        ctx.lineTo(this.x2, this.y1);
        ctx.lineTo(this.x3, this.y1);
        ctx.arcTo(this.x3, this.y2, this.x4, this.y2, this.options.radius);
        ctx.lineTo(this.x4, this.y2);
        ctx.lineTo(this.x4, this.y3);
        ctx.arcTo(this.x3, this.y3, this.x3, this.y4, this.options.radius);
        ctx.lineTo(this.x3, this.y4);
        ctx.lineTo(this.x2, this.y4);
        ctx.arcTo(this.x2, this.y3, this.x1, this.y3, this.options.radius);
        ctx.lineTo(this.x1, this.y3);
        ctx.closePath();
        ctx.fill();
        ctx.restore();
    };

    //draw crosswalk
    CanvasCross.prototype.crosswalk = function(ctx) {
        var numberY = Math.ceil(parseInt(this.options.horizontal.width) / 15);
        var numberX = Math.ceil(parseInt(this.options.vertical.width) / 15);
        ctx.fillStyle = '#7C7C7C';
        ctx.save();
        ctx.translate(this.x2 - this.options.radius, this.y2);
        for (var i = 0; i < numberY; i++) {
            ctx.fillRect(0, 15 * i, 30, 4);
        }
        ctx.restore();
        ctx.save();
        ctx.translate(this.x3 + this.options.radius - 30, this.y2);
        for (var i = 0; i < numberY; i++) {
            ctx.fillRect(0, 15 * i, 30, 4);
        }
        ctx.restore();

        ctx.save();
        ctx.translate(this.x2, this.y2 - this.options.radius/2+5);
        ctx.rotate(-Math.PI / 2);
        for (var i = 0; i < numberX; i++) {
            ctx.fillRect(0, 15 * i, 30, 4);
        }
        ctx.restore();

        ctx.save();
        ctx.translate(this.x2, this.y3 + this.options.radius);
        ctx.rotate(-Math.PI / 2);
        for (var i = 0; i < numberX; i++) {
            ctx.fillRect(0, 15 * i, 30, 4);
        }
        ctx.restore();
    }

    // draw drive
    CanvasCross.prototype.drive = function(ctx) {
        /*way line*/
        var wayHor = this.wayHor = Math.ceil(parseInt(this.options.horizontal.width) / 6);
        var wayVer = this.wayVer = Math.ceil(parseInt(this.options.vertical.width) / 4);
        ctx.save();
        ctx.strokeStyle = "#7C7C7C";
        ctx.lineWidth = 2;
        for (var i = 1; i < 6; i++) {
            ctx.beginPath();
            ctx.moveTo(this.x1, this.y2 + wayHor * i);
            ctx.lineTo(this.x2 - this.options.radius, this.y2 + wayHor * i);
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(this.x4, this.y2 + wayHor * i);
            ctx.lineTo(this.x3 + this.options.radius, this.y2 + wayHor * i);
            ctx.stroke();
        }
        for (var n = 1; n < 4; n++) {
            ctx.beginPath();
            ctx.moveTo(this.x2 + wayVer * n, this.y1);
            ctx.lineTo(this.x2 + wayVer * n, this.y2 - this.options.radius);
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(this.x2 + wayVer * n, this.y4);
            ctx.lineTo(this.x2 + wayVer * n, this.y3 + this.options.radius);
            ctx.stroke();
        }
        ctx.restore();

        /*wran line*/
        ctx.save();
        ctx.strokeStyle = "#B88E1F";
        ctx.lineWidth = 3.5;
        //left horizontal
        ctx.beginPath();
        ctx.moveTo(this.x1, this.height / 2 +1);
        ctx.lineTo(this.x2 - this.options.radius, this.height / 2 +1);
        ctx.stroke();
        //right horizontal
        ctx.beginPath();
        ctx.moveTo(this.x4, this.height / 2 + 1);
        ctx.lineTo(this.x3 + this.options.radius, this.height / 2 +1);
        ctx.stroke();
        //top vertical
        ctx.beginPath();
        ctx.moveTo(this.width / 2, this.y1);
        ctx.lineTo(this.width / 2, this.y2 - this.options.radius);
        ctx.stroke();
        //bottom vertical
        ctx.beginPath();
        ctx.moveTo(this.width / 2, this.y4);
        ctx.lineTo(this.width / 2, this.y3 + this.options.radius);
        ctx.stroke();
        ctx.restore();
    }
    //绘制道路名称
    CanvasCross.prototype.text = function(ctx){
        ctx.save();
        ctx.font = "16px Arial";
        ctx.fillStyle = "#fff";
        ctx.beginPath();
        ctx.fillText(this.options.horizontal.name, parseInt(this.options.horizontal.text.left), this.y2 - 20);
        ctx.fillText(this.options.horizontal.name, this.x4 - parseInt(this.options.horizontal.text.right), this.y3 + 30);
        this.pathText(this.options.vertical.name, this.x2 - 30, parseInt(this.options.vertical.text.top), 18);
        this.pathText(this.options.vertical.name, this.x3 + 30, this.y4 - parseInt(this.options.vertical.text.bottom), 18);
        ctx.restore();
    }
    //绘制道路名称
    CanvasCross.prototype.pathText = function(string, x, y, size){
        //绘制竖排文字
        var index = 0,
            ctx = this.ctx,
            charText;
        ctx.save();
        while(index < string.length){
            charText = string.charAt(index);
            ctx.save();
            ctx.beginPath();
            ctx.fillText(charText, x, y);
            ctx.restore();
            y = y + size;
            index++;
        }
        ctx.restore();
    }
    /**
     * [arrow 道路指向]
     * @param  {[type]} direction [方向]
     * @param  {[type]} position  [转向]
     * @return {[type]}           [定时器对象]
     */
    CanvasCross.prototype.arrow = function(position, x, y, size, angle) {
        if(!x || !y){
            throw ('x or y is undefiund');
            return;
        }
        var ctx = this.ctx;
        var that = this;
        var startRad = Math.PI*angle / 180;
        clearInterval(that.timer);
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        that.draw();
        var timer = that.timer = window.setInterval(function() {
            var date = new Date();
            var seconds = date.getSeconds();
            if (seconds % 2) {
                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                that.draw();
            } else {
                ctx.save();
                ctx.fillStyle = "#fff";
                if (position == "middle") {
                    ctx.save(); 
                    ctx.translate(x, y);
                    ctx.scale(size, size);   
                    ctx.rotate(startRad);    
                    ctx.beginPath();
                    ctx.moveTo(0, 0);
                    ctx.lineTo(60, 0);
                    ctx.lineTo(60, -3);
                    ctx.lineTo(70, 2);
                    ctx.lineTo(60, 7);
                    ctx.lineTo(60, 4);
                    ctx.lineTo(0, 4);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                } else if (position == "right") {
                    ctx.save(); 
                    ctx.translate(x, y);
                    ctx.scale(size, size);   
                    ctx.rotate(startRad);    
                    ctx.beginPath();
                    ctx.moveTo(0, -5);
                    ctx.lineTo(60, -5);
                    ctx.lineTo(60, 5);
                    ctx.lineTo(63, 5);
                    ctx.lineTo(58, 15);
                    ctx.lineTo(53, 5);
                    ctx.lineTo(56, 5);
                    ctx.lineTo(56, -1);
                    ctx.lineTo(0, -1);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                } else if (position == "left") {
                    ctx.save(); 
                    ctx.translate(x, y);
                    ctx.scale(size, size);
                    ctx.rotate(startRad);
                    ctx.beginPath();
                    ctx.moveTo(0, 2);
                    ctx.lineTo(56, 2);
                    ctx.lineTo(56, -4);
                    ctx.lineTo(53, -4);
                    ctx.lineTo(58, -14);
                    ctx.lineTo(63, -4);
                    ctx.lineTo(60, -4);
                    ctx.lineTo(60, 6);
                    ctx.lineTo(0, 6);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                }else if(position == "middleLeft"){
                    ctx.save(); 
                    ctx.translate(x, y);
                    ctx.scale(size, size);
                    ctx.rotate(startRad);
                    ctx.beginPath();
                    ctx.moveTo(0, 0);
                    ctx.lineTo(60, 0);
                    ctx.lineTo(60, -3);
                    ctx.lineTo(70, 2);
                    ctx.lineTo(60, 7);
                    ctx.lineTo(60, 4);
                    ctx.lineTo(0, 4);
                    ctx.closePath();
                    ctx.fill();
                    ctx.beginPath();
                    ctx.moveTo(50, 0);
                    ctx.lineTo(50, -4);
                    ctx.lineTo(47, -4);
                    ctx.lineTo(52, -14);
                    ctx.lineTo(57, -4);
                    ctx.lineTo(54, -4);
                    ctx.lineTo(54, 0);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                }else if(position == "middleRight"){
                    ctx.save(); 
                    ctx.translate(x, y);
                    ctx.scale(size, size);
                    ctx.rotate(startRad);
                    ctx.beginPath();
                    ctx.moveTo(0, 0);
                    ctx.lineTo(60, 0);
                    ctx.lineTo(60, -3);
                    ctx.lineTo(70, 2);
                    ctx.lineTo(60, 7);
                    ctx.lineTo(60, 4);
                    ctx.lineTo(0, 4);
                    ctx.closePath();
                    ctx.fill();
                    ctx.beginPath();
                    ctx.moveTo(50, 0);
                    ctx.lineTo(50, 8);
                    ctx.lineTo(47, 8);
                    ctx.lineTo(52, 18);
                    ctx.lineTo(57, 8);
                    ctx.lineTo(54, 8);
                    ctx.lineTo(54, 0);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                }
                ctx.restore();
            }
        }, 1000 / 2);
    }
    return CanvasCross;
}))